//
//  NetWorkingManager.swift
//  Crypto
//
//  Created by DaleGuo on 2023/9/22.
//

import Combine
import Foundation

/// 通用处理网络，主要在Service中调用
class NetWorkingManager {
    enum NetworkingError: LocalizedError {
        // 自定义错误
        case badURLResponse(url: URL) // 甚至可以传参
        case unowned

        var errorDescription: String? {
            switch self {
            case .badURLResponse(url: let url): return "[🔥]Bad Response form URL (custom error) : \(url)"
            case .unowned: return "[⚠️]Unknow Error (custom error)"
            }
        }
    }

    // 静态化都能用
    // 不知道return类型，可以为其创建变量，option点击访问
    static func download(url: URL) -> AnyPublisher<Data, Error> {
        return URLSession.shared.dataTaskPublisher(for: url)
            .subscribe(on: DispatchQueue.global(qos: .default)) // 后台订阅
            .tryMap { try handleURLResponse(output: $0, url: url) } // 函数为参，静态方法只能调用静态方法
            .retry(3) // 失败了自动尝试3次
//            .receive(on: DispatchQueue.main) // 优化 将decode放在后台线程完成，所以将receive on 放在dechode之后
            .eraseToAnyPublisher() // 转为anyPub，简化return值
    }

    static func handleURLResponse(output: URLSession.DataTaskPublisher.Output, url: URL) throws -> Data {
//        throw NetworkingError.badURLResponse(url: url)  //强制error测试自定义error
        guard let response = output.response as? HTTPURLResponse,
              response.statusCode >= 200, response.statusCode < 300
        else {
            // 返回自定义错误
            throw NetworkingError.badURLResponse(url: url)
        }
        return output.data
    }

    // handle the out
    static func handleCompletion(completion: Subscribers.Completion<Publishers.Decode<AnyPublisher<Data, Error>, [CoinModel], JSONDecoder>.Failure>) {
        switch completion { // 由于trymap可能throws 所以sink有多个completion
        case .finished:
            break
        case .failure(let error):
            print(error.localizedDescription)
        }
    }
}
